package com.write.program.socket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.write.program.socket.message.*;
import com.write.program.socket.util.ServerLoginUtil;

import java.io.IOException;
import java.net.Socket;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Endstart
 * Date: 2019-11-20
 * Time: 23:14
 */
public class ServerSocketService extends SocketService {
    private LoginInfo loginInfo = null;
    private ServerManager serverManager;

    public ServerSocketService(Socket socket, ServerManager serverManager) {
        super(socket);
        this.serverManager = serverManager;
    }

    @Override
    public Message processReceiveMessage(JSONObject messageObj) {
        int type = messageObj.getIntValue("type");
        try {
            switch (type) {
                case MessageConst.LOGIN_MESSAGE_TYPE:
                    return checkLogin(JSON.toJavaObject(messageObj, LoginMessage.class));

                case MessageConst.LOGOUT_MESSAGE_TYPE:
                    checkLogout(JSON.toJavaObject(messageObj, LogoutMessage.class));
                    break;
                case MessageConst.CHAT_MESSAGE_TYPE:
                    chatMessageTransfer(JSON.toJavaObject(messageObj, ChatMessage.class));
                    break;

                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 消息转发
     *
     * @param message
     * @throws IOException
     */
    private NoticeMessage chatMessageTransfer(ChatMessage message) throws IOException {
        message.setFromUserName(loginInfo.userName);
        // 对方是否存在
        if (!ServerLoginUtil.contains(message.getToUserName())) {
            return new NoticeMessage("Error. Invalid user");
        }

        // 不能给自己发
        if (message.getFromUserName().equalsIgnoreCase(message.getToUserName())) {
            return new NoticeMessage("Error. Cannot send to self");
        }

        for (SocketService socketService : serverManager.getSocketManagerSet()) {
            ServerSocketService serverSocketService = (ServerSocketService) socketService;
            if (serverSocketService.loginInfo != null && serverSocketService.loginInfo.userName.equals(message.getToUserName())) {
                try {
                    serverSocketService.sendMessage(message);
                    return null;
                } catch (IOException e) {
                    throw e;
                }
            }
        }
        return null;
    }


    /**
     * 登陆，登陆成功后进行广播时下发离线消息
     *
     * @param message
     * @return
     * @throws IOException
     */
    private Message checkLogin(LoginMessage message) throws IOException {
        loginInfo = new LoginInfo();
        loginInfo.userName = message.getUserName();
        loginInfo.password = message.getPassword();
        if (ServerLoginUtil.checkAndLogin(loginInfo)) {
            message.setCode(LoginMessage.SUCCESS_CODE);
            loginBroadCase(message);
        } else {
            message.setCode(LoginMessage.FAILED_CODE);
        }
        return message;
    }

    /**
     * 登出
     * @param message
     */
    private void checkLogout(LogoutMessage message) throws IOException {
        socket.close();
        serverManager.removeServerSocket(this);
        message.setUsername(loginInfo.userName);
        logoutBroadCase(message);

        loginInfo = null;
        this.getSocket().close();
        this.interrupt();
    }

    /**
     * 登陆成功后广播其他用户
     *
     * @param message
     */
    private void loginBroadCase(LoginMessage message) throws IOException {
        String msg = loginInfo.userName + " logged in";
        BroadcastMessage broadcastMessage = new BroadcastMessage();
        broadcastMessage.setFromUserName(message.getUserName());
        broadcastMessage.setMsg(msg);
        broadCase(broadcastMessage);
    }

    /**
     * 登出后广播其他用户
     *
     * @param message
     */
    private void logoutBroadCase(LogoutMessage message) throws IOException {
        String msg = loginInfo.userName + " logged out";
        BroadcastMessage broadcastMessage = new BroadcastMessage();
        broadcastMessage.setFromUserName(message.getUsername());
        broadcastMessage.setMsg(msg);
        broadCase(broadcastMessage);
    }

    /**
     * 广播其他用户
     *
     * @param message
     */
    private void broadCase(BroadcastMessage message) throws IOException {
        StringBuffer stringBuffer = new StringBuffer();
        for (SocketService socketService : serverManager.getSocketManagerSet()) {
            ServerSocketService serverSocketService = (ServerSocketService) socketService;
            serverSocketService.sendMessage(message);
        }
    }

    /**
     * 当前是否登陆
     * @return
     */
    public boolean isLogin() {
        return loginInfo != null && loginInfo.userName != null;
    }

    /**
     * 当前登陆者
     * @return
     */
    public String getLoginUsername() {
        if (loginInfo != null) {
            return loginInfo.userName;
        }
        return null;
    }

    public static class LoginInfo {
        public String userName;
        public String password;
        public String loginToken;
    }
}
